package com.sayimo.maker.commons.utils;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;


/**
 * @Project: schoolmallapi-dev1.1
 * @ClassName: RedisUtils
 * @Description: 
 * @author:	chenpy
 * @date:	2016年6月27日
 * @version 1.0.0
 */
public class RedisUtils {
	
	private static JedisPool jedisPool;
	
	public static String GOODSINDEX_CACHE;
	
	public static String GOODSCLASS_CACHE;
	
	public static String PROVIDER_CLASSIDS_CACHE;
	
	private static Log logger = LogFactory.getLog(RedisUtils.class);
	
	static{
		
		int port = Integer.parseInt(PropertiesUtils.getValue("redis.port")),
				maxIdle = Integer.parseInt(PropertiesUtils.getValue("redis.pool.maxIdle")),
				maxWait = Integer.parseInt(PropertiesUtils.getValue("redis.pool.maxWait"));
		String host = PropertiesUtils.getValue("redis.host"),
				pass = StringUtils.isEmpty(PropertiesUtils.getValue("redis.pass")) ? null : PropertiesUtils.getValue("redis.pass");
		boolean testOnBorrow = Boolean.parseBoolean(PropertiesUtils.getValue("redis.pool.testOnBorrow"));
		
		GOODSINDEX_CACHE = PropertiesUtils.getValue("redis.cache.prefix") + "$GOODSINDEX_";
		GOODSCLASS_CACHE = PropertiesUtils.getValue("redis.cache.prefix") + "$GOODSCLASS_";
		PROVIDER_CLASSIDS_CACHE = PropertiesUtils.getValue("redis.cache.prefix") + "$PROVIDER_CLASSIDS_";
		
		/*int port = 6363, maxIdle = 20, maxWait = 3000;
		boolean testOnBorrow = true;
		String host = "14.215.136.20", pass = "Sayimo!@#123Redis";*/
				
		// String host = "120.24.175.40";
		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxIdle(maxIdle);
		config.setMaxWaitMillis(maxWait);
		config.setTestOnBorrow(testOnBorrow);
		jedisPool = pass == null ? new JedisPool(config, host, port, 6000) : new JedisPool(config, host, port, 6000, pass);
	}
	
	private static Jedis popJedisConnection(){
		return jedisPool.getResource();
	}
	
	private static void closeJedisConnection(Jedis jedis){
		if (jedis != null) {
			jedis.close();
		}
	}
	
	public static boolean hasKey(String key){
		logger.info("key = " + key);
		Jedis jedis = popJedisConnection();
		try{
			return jedis.keys("*").contains(key);
		} finally{
			closeJedisConnection(jedis);
		}
	}
	
	/** 
	  * @package com.sayimo.school.mall.util
	  * @author chenpy
	  * @Title:  
	  * @Description: 
	  * @param 
	  * @throws 
	  * @return List<T>
	  * @date 2016年6月27日
	  */ 
	@SuppressWarnings("unchecked")
	public static <T> List<T> getListCache(String key, Integer start, Integer end, Class<T> clazz){
		
		Jedis jedis = popJedisConnection();
		try{
			logger.info("key = " + key);
			Set<String> bulks = jedis.keys(key);
			if (CollectionUtils.isEmpty(bulks)) {
				logger.info("key not exists in redis!");
				return null;
			}
			
			String keyType = jedis.type(key);
			logger.info("keyType = " + keyType);
			
			Integer startPosition = 0, endPosition = 0;
			ArrayList<T> valueList = null;
			if (keyType.toUpperCase().equals("STRING")) {
				JsonParser jsonParser = new JsonParser();
				String value = jedis.get(key);
				logger.info("value = " + value);
				JsonElement element = jsonParser.parse(value);
				if (element.isJsonObject()) {
					JsonObject jsonObject = element.getAsJsonObject();
					logger.info(jsonObject.toString());
					valueList = new ArrayList<>();
					valueList.add((T) JSONUtil.readValueToMap(value));
					return valueList;
				}
				
				valueList = (ArrayList<T>) JSONUtil.readValueToBeanList(jedis.get(key), clazz);
				if (start != null) {
					startPosition = start;
				}
				if (end != null) {
					endPosition = valueList.size() > end ? end : valueList.size();
				}

				if (start != null && end != null) {
					return valueList.subList(startPosition, endPosition);
				}
				
				return valueList;
			} else if(keyType.toUpperCase().equals("LIST")){
				Long valueLength = jedis.llen(key);
				
				if (start != null) {
					startPosition = start;
				}
				if (end != null) {
					endPosition = valueLength.intValue() > end ? end : valueLength.intValue();
				}
				
				if (start != null && end != null) {
					return (List<T>) jedis.lrange(key, startPosition, endPosition);
				}
				
				List l = jedis.lrange(key, 0, 1000);
				return JSONUtil.readValueToBeanList(JSONUtil.writeValueAsString(l), clazz);
			}
			
			return null;
		}finally{
			closeJedisConnection(jedis);
		}
	}
	
	/**
		 * @Package com.sayimo.maker.commons.utils
		 * @Author 谭新
		 * @MethodName: put
		 * @Description: 往redis存放数据
		 * @return void
		 * @Date 2017年3月25日,下午2:19:28
		 */
	public static void put(String key, String value){
		Jedis jedis = null;
		try {
			jedis = popJedisConnection();
			// jedis.expire(key, 24 * 60 * 60 * 7);
			logger.info("key = " + key);
			logger.info("value = " + value);
			
			jedis.set(key, value);
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			closeJedisConnection(jedis);
		}
	}
	
	/**
	 * @Package com.sayimo.maker.commons.utils
	 * @Author 谭新
	 * @MethodName: removeKey
	 * @Description: 从redis移除KEY
	 * @return void
	 * @Date 2017年3月25日,下午2:19:06
	 */
	public static void removeKey(String key){
		Jedis jedis = null;
		try {
			jedis = popJedisConnection();
			jedis.del(key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			closeJedisConnection(jedis);
		}
	}
	
	/**
	 * @Package com.sayimo.maker.commons.utils
	 * @Author 谭新
	 * @MethodName: getStringValue
	 * @Description: 获取redis字符串值
	 * @return void
	 * @Date 2017年3月25日,下午2:19:06
	 */
	public static String getStringValue(String key){
		Jedis jedis = null;
		try {
			jedis = popJedisConnection();
			return jedis.get(key);
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			closeJedisConnection(jedis);
		}
		
		return null;
	}
	
	public static void main(String[] args) {
		for (int i = 0; i < 1000; i++) {
			List<Map> values = RedisUtils.getListCache("$REDIS_CACHE_DEV_MAKER_$GOODSINDEX_markerClient_APP_HOME", null, null, Map.class);
			System.out.println(JSONUtil.writeValueAsString(values));
		}
	}
}
